﻿#region Usings

using System;
using System.Collections.Generic;
using System.Linq;

#endregion

namespace Mp3Observer.Common
{
    /// <summary>
    /// Beinhaltet ExtensionMethods für IEnumerable.
    /// </summary>
    /// <remarks>Ausnahmsweise repräsentiert der Klassenname die Mehrzahl, da es ansonsten zu Namenskonflikten kommen kann.</remarks>
    public static class Enumerable
    {
        /// <summary>
        /// Transforms the specified input.
        /// </summary>
        /// <typeparam name="TInput">The type of the input.</typeparam>
        /// <typeparam name="TOutput">The type of the output.</typeparam>
        /// <param name="input">The input.</param>
        /// <param name="transformer">The transformer.</param>
        /// <returns>the transformed outpout</returns>
        public static IEnumerable<TOutput> Transform<TInput, TOutput>(this IEnumerable<TInput> input, Converter<TInput, TOutput> transformer)
        {
            foreach (var item in input)
                yield return transformer(item);
        }

        /// <summary>
        /// Does a foreach on the source with the action on any item.
        /// </summary>
        /// <typeparam name="TSource">The type of the source.</typeparam>
        /// <param name="source">The source.</param>
        /// <param name="action">The action.</param>
        /// <returns>the source</returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "1", Justification = "CheckIfParameterIsNull not recognised from CodeAnalysis")]
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "CheckIfParameterIsNull not recognised from CodeAnalysis")]
        public static IEnumerable<TSource> ForEach<TSource>(this IEnumerable<TSource> source, Action<TSource> action)
        {
            Helper.CheckIfParameterIsNull(source, "source");
            Helper.CheckIfParameterIsNull(action, "action");

            foreach (TSource item in source)
                action(item);
            return source;
        }

        /// <summary>
        /// Searches for the element and returns the next element.
        /// </summary>
        /// <typeparam name="TSource">The type of the source.</typeparam>
        /// <param name="source">The source.</param>
        /// <param name="element">The element.</param>
        /// <returns>the next element after the specified element.</returns>
        public static TSource TakeNextElement<TSource>(this IEnumerable<TSource> source, TSource element) where TSource : class
        {
            bool found = false;
            foreach (TSource item in source)
            {
                if (found)
                    return item;
                if (item.Equals(element))
                    found = true;
            }
            return null;
        }

        /// <summary>
        /// Searches for the element and returns the previous element.
        /// </summary>
        /// <typeparam name="TSource">The type of the source.</typeparam>
        /// <param name="source">The source.</param>
        /// <param name="element">The element.</param>
        /// <returns>the previous element before the specified element.</returns>
        public static TSource TakePreviousElement<TSource>(this IEnumerable<TSource> source, TSource element) where TSource : class
        {
            Helper.CheckIfParameterIsNull(source, "source");

            TSource prevElement = null;
            foreach (TSource item in source)
            {
                if (item.Equals(element))
                    return prevElement;
                prevElement = item;
            }
            return null;
        }

        /// <summary>
        /// Determines whether [is equal to all] [the specified source].
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="equalityTargets">The equality targets.</param>
        /// <returns>
        /// <c>true</c> if [is equal to all] [the specified source]; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsEqualToAll(this string source, IList<string> equalityTargets)
        {
            Helper.CheckIfParameterIsNull(equalityTargets, "equalityTargets");
            Helper.CheckIfParameterIsNull(source, "source");

            bool found = true;
            foreach (var equalityTarget in equalityTargets)
                if (source == null && equalityTarget != null)
                    return false;
                else
                {
                    if (source == null && equalityTarget == null)
                        return true;
                    else
                        if (!source.Contains(equalityTarget))
                            return false;
                }
            return found;
        }
    }
}
